<template>
  <view class="upload-container">
    <view>
      <movable-area class="pic-wrap" :style="{ height: data.areaHeight }">
        <movable-view
          class="movable-view"
          :x="item.x"
          :y="item.y"
          :style="{
            width: data.viewWidth + 'px',
            height: data.viewWidth + 'px',
            opacity: item.opacity,
            zIndex: item.zIndex,
          }"
          direction="all"
          v-for="(item, index) in data.list"
          :key="index"
          @change="onChange($event, item)"
          @touchstart="touchstart(item)"
          @touchend="touchend(item)"
        >
          <image
            class="pic"
            :lazy-load="true"
            :show-menu-by-longpress="true"
            :style="{
              width: data.imageWidth + 'rpx',
              height: data.imageWidth + 'rpx',
              opacity: item.opacity,
              transform: `scale(${item.scale})`,
            }"
            :src="item.src"
            @click.stop="preview(item)"
            mode="aspectFill"
          />
          <view
            class="del-box"
            @touchstart.stop="del(item, index)"
            @click.stop="del(item, index)"
          >
            <text class="nb_icon icon_close"></text>
          </view>
        </movable-view>
        <view
          class="pic-box"
          @click="choosePic()"
          v-if="props.limit > data.list.length"
          :style="{
            width: data.imageWidth + 'rpx',
            top: data.add.y,
            left: data.add.x,
            height: data.imageWidth + 'rpx',
          }"
        >
          <view>
            <view class="nb_icon icon_camera"></view>
            <view class="text">上传图片</view>
          </view>
        </view>
      </movable-area>
    </view>
    <uni-popup ref="pop" :mask-click="false"></uni-popup>
  </view>
</template>
<script setup lang="ts">
import { getQiniuConfig } from "@/apis/member.ts";
import { reactive, getCurrentInstance, onMounted, nextTick, ref } from "vue";
const { proxy } = getCurrentInstance();
const emit = defineEmits(["success"]);
const pop = ref();
const props = defineProps({
  width: {
    type: Number,
    default: 0,
  },
  picList: {
    type: Array,
    default: [],
  },
  limit: {
    type: Number,
    default: 9,
  },
});
const data = reactive({
  list: [],
  add: {
    x: 0,
    y: 0,
  },
  x: 0,
  y: 0,
  picIndex: "",
  scale: 1.1,
  opacity: 0.7,
  timer: null,
  areaHeight: 0,
  imageWidth: 230, //图片宽度
  windowWidth: 0, //屏幕宽度
  viewWidth: 0, //图片框宽度
  colsValue: 0, //多少栏
  changeStatus: true,
});
onMounted(() => {
  data.imageWidth = props.width || 230;
  moveInit();
});
const moveInit = () => {
  data.windowWidth = uni.getSystemInfoSync().windowWidth;
  data.viewWidth = rpx2px(data.imageWidth);
  const query = uni.createSelectorQuery().in(getCurrentInstance());
  query.select(".pic-wrap").boundingClientRect((areaData: any) => {
    data.colsValue = Math.floor(areaData.width / data.viewWidth);
    handleHeight();
    props.picList.forEach((ele: any) => {
      addProperties(ele);
    });
  });
  query.exec();
};
const rpx2px = (v: any) => {
  return (data.windowWidth * v) / 750;
};
const touchstart = (item: any) => {
  data.list.forEach((v: any) => {
    v.zIndex = v.index + 9;
  });
  item.zIndex = 99;
  data.timer = setTimeout(() => {
    item.scale = data.scale;
    item.opacity = data.opacity;
    clearTimeout(data.timer);
    data.timer = null;
  }, 200);
};
const touchend = (item: any) => {
  item.scale = 1;
  item.opacity = 1;
  item.x = item.oldX;
  item.y = item.oldY;
  item.offset = 0;
  item.moveEnd = false;
  setTimeout(() => {
    nextTick(() => {
      item.x = item.absX * data.viewWidth;
      item.y = item.absY * data.viewWidth;
      data.tempItem = null;
      data.changeStatus = true;
    });
  }, 0);
  sortList();
};

const onChange = (e: any, item: any) => {
  if (!item) return;
  item.oldX = e.detail.x;
  item.oldY = e.detail.y;
  if (e.detail.source === "touch") {
    if (item.moveEnd) {
      item.offset = Math.sqrt(
        Math.pow(item.oldX - item.absX * data.viewWidth, 2) +
          Math.pow(item.oldY - item.absY * data.viewWidth, 2)
      );
    }
    console.log(data.viewWidth);
    let x = Math.floor((e.detail.x + data.viewWidth / 2) / data.viewWidth);
    console.log(x);
    if (x >= data.colsValue) return;
    let y = Math.floor((e.detail.y + data.viewWidth / 2) / data.viewWidth);
    let index = data.colsValue * y + x;
    if (item.index != index && index < data.list.length) {
      data.changeStatus = false;
      for (let obj of data.list) {
        if (
          item.index > index &&
          obj.index >= index &&
          obj.index < item.index
        ) {
          change(obj, 1);
        } else if (
          item.index < index &&
          obj.index <= index &&
          obj.index > item.index
        ) {
          change(obj, -1);
        } else if (obj.id != item.id) {
          obj.offset = 0;
          obj.x = obj.oldX;
          obj.y = obj.oldY;
          setTimeout(() => {
            nextTick(() => {
              obj.x = obj.absX * data.viewWidth;
              obj.y = obj.absY * data.viewWidth;
            });
          }, 0);
        }
      }
      item.index = index;
      item.absX = x;
      item.absY = y;
    }
  }
};
const change = (obj: any, i: any) => {
  obj.index += i;
  obj.offset = 0;
  obj.x = obj.oldX;
  obj.y = obj.oldY;
  obj.absX = obj.index % data.colsValue;
  obj.absY = Math.floor(obj.index / data.colsValue);
  setTimeout(() => {
    nextTick(() => {
      obj.x = obj.absX * data.viewWidth;
      obj.y = obj.absY * data.viewWidth;
    });
  }, 0);
};

const sortList = () => {
  let list = data.list.slice();
  list.sort((a: any, b: any) => {
    return a.index - b.index;
  });
  let endList: any = [];
  list.forEach((ele: any, i: any) => {
    endList.push(ele.src);
  });
  emit("success", endList);
  // data.list = list;
};

const addProperties = (item: any) => {
  let absX = data.list.length % data.colsValue;
  let absY = Math.floor(data.list.length / data.colsValue);
  let x = absX * data.viewWidth;
  let y = absY * data.viewWidth;
  data.list.push({
    src: item,
    x,
    y,
    oldX: x,
    oldY: y,
    absX,
    absY,
    scale: 1,
    zIndex: 9,
    opacity: 1,
    index: data.list.length,
    disable: false,
    offset: 0,
    moveEnd: false,
  });
  sortList();
  data.add.x = (data.list.length % data.colsValue) * data.viewWidth + "px";
  data.add.y =
    Math.floor(data.list.length / data.colsValue) * data.viewWidth + "px";
};

const choosePic = (index: any = "") => {
  if (index) {
    data.picIndex = index;
  }
  uni.chooseImage({
    count: props.limit, //默认9
    sizeType: ["compressed"], //可以指定是原图还是压缩图，默认二者都有
    success: (res: any) => {
      pop.value.open();
      uni.showLoading({
        title: "正在上传",
      });
      getKey(res.tempFilePaths);
    },
  });
};
const preview = (item: any) => {
  uni.previewImage({
    urls: props.picList,
    current: item.src,
    success: () => {
      setTimeout(() => {
        item.scale = 1;
        item.opacity = 1;
      }, 300);
    },
  });
};
const getKey = async (tempFilePaths: any) => {
  for (let ele of tempFilePaths) {
    // #ifdef MP-WEIXIN
    let res: any = await new Promise((resolve) => {
      uni.compressImage({
        src: ele,
        quality: 80,
        success: (res) => {
          resolve(res);
        },
      });
    });
    // #endif

    let qiuniuRes: any = await getQiniuConfig();
    // #ifdef MP-WEIXIN
    await upload(res.tempFilePath, qiuniuRes.data.uploadToken);
    // #endif
    // #ifdef H5
    await upload(ele, qiuniuRes.data.uploadToken);
    // #endif
  }
  pop.value.close();
  uni.hideLoading();
  handleHeight();
};
const upload = async (url: any, token: any) => {
  return new Promise((resolve: any, reject: any) => {
    uni.uploadFile({
      url: "https://up.qiniup.com",
      name: "file",
      filePath: url,
      formData: {
        token: token,
      },
      success: (res: any) => {
        if (res.data) {
          let response = JSON.parse(res.data);
          if (data.picIndex) {
            data.list.splice(data.picIndex - 1, 1, {
              src: `${proxy.$baseUrl.imageUrl}/${response.key}`,
            });
            resolve();
          } else {
            addProperties(`${proxy.$baseUrl.imageUrl}/${response.key}`);
            resolve();
          }
        }
      },
      fail: (error: any) => {
        reject(error);
      },
    });
  });
};
const handleHeight = () => {
  if (props.picList.length < props.limit) {
    data.areaHeight =
      Math.ceil((props.picList.length + 1) / data.colsValue) * data.viewWidth +
      "px";
  } else {
    data.areaHeight =
      Math.ceil(props.picList.length / data.colsValue) * data.viewWidth + "px";
  }
};
const del = (item: any, index: any) => {
  uni.showModal({
    title: "提示",
    content: "确认删除该文件吗？",
    cancelColor: "#999999",
    confirmColor: "#596C95",
    success: (res) => {
      if (res.confirm) {
        data.list.splice(index, 1);
        for (let obj of data.list) {
          if (obj.index > item.index) {
            obj.index -= 1;
            obj.x = obj.oldX;
            obj.y = obj.oldY;
            obj.absX = obj.index % data.colsValue;
            obj.absY = Math.floor(obj.index / data.colsValue);
            nextTick(() => {
              obj.x = obj.absX * data.viewWidth;
              obj.y = obj.absY * data.viewWidth;
            });
          }
        }
        data.add.x =
          (data.list.length % data.colsValue) * data.viewWidth + "px";
        data.add.y =
          Math.floor(data.list.length / data.colsValue) * data.viewWidth + "px";
        sortList();
      }
    },
  });
};
</script>
<style lang="scss" scoped>
@import url("@/static/css/theme.scss");
.upload-container {
  .pic-wrap {
    position: relative;
    width: 100vw;
    height: 500rpx;
    .movable-view {
      .pic {
        width: 210rpx;
        height: 210rpx;
        border-radius: 14rpx;
      }
      .del-box {
        position: absolute;
        top: -30rpx;
        right: 0;
        padding: 10rpx;
        .icon_close {
          color: #fff;
          font-size: 24rpx;
          padding: 4rpx;
          border-radius: 15rpx;
          background-color: #888;
          z-index: 999;
        }
      }
    }
    .pic-box {
      position: absolute;
      width: 210rpx;
      height: 210rpx;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      text-align: center;
      background: #f9f9f9;
      border-radius: 14rpx;
      font-size: 24rpx;
      color: #666666;
      .pic {
        width: 210rpx;
        height: 210rpx;
        border-radius: 14rpx;
      }

      .icon_camera {
        font-size: 50rpx;
      }
      .text {
        margin-top: 8rpx;
      }
    }
  }
}
</style>
